<?php
set_include_path('/usr/share/php/phptal/'.':'.'/usr/share/php/smarty'.':'.get_include_path());
error_reporting(E_ALL);
ini_set('display_errors', 1);
class Timer {
	protected $start ;
	function start() {
		$this->start = microtime(true);
	}
	function stop(){
		return microtime(true) - $this->start;
	}
}
class TestProvider {
	protected $array = array();
	function classLoad(){}
	function objectCreation(){}
	function emptyTemplate(){}
	function emptyTemplateCached(){}
	function __construct() {
		$this->array = range(1,100);
		$this->table = array();
		foreach(range(1,20) as $row) {
				$this->table[$row] = array(1,20);
		}
	}
	function listTemplateOutput() {
		$this->array = range(1,5);
		echo '<div style="float:left;"><h2>List output test</h2><div>';
		echo $this->listTemplate();
		echo '</div></div>';
	}
	function tableTemplateOutput() {
		$this->table = array();
		foreach(range(1,4) as $row) {
				$this->table[$row] = range($row*4,$row*4+4);
		}
		echo '<div style="float:left;"><h2>Table output test</h2><div>';
		echo $this->tableTemplate();
		echo '</div></div>';
	}
}
class MicroTalProvider extends TestProvider{
	/**
	 * @var MicroTal
	 */
	private $mock ;
	function classLoad() {
		require_once 'MicroTal.php';
	}
	function objectCreation() {
		$this->mock =  new MicroTal();
		$this->mock->setRelativeTemplateDir('benchmark');
	}
	function emptyTemplate() {
		$this->mock->setCacheEnabled(false);
		$this->mock->execute("empty.xhtml");
	}
	function emptyTemplateCached() {
		$this->mock->setCacheEnabled(true);
		$this->mock->execute("empty.xhtml");
	}
	function listTemplate() {
		$this->mock->list = $this->array;
		$this->mock->setCacheEnabled(true);
		return $this->mock->execute("list.xhtml");
	}
	function tableTemplate() {
		$this->mock->table = $this->table;
		$this->mock->setCacheEnabled(true);
		return $this->mock->execute("table.xhtml");
	}
}
class PhpTalProvider extends TestProvider{
	/**
	 * @var PHPTAL
	 */
	private $mock ;
	function classLoad() {
		require_once 'PHPTAL.php';
	}
	function objectCreation() {
		$this->mock =  new PHPTAL();
		$this->mock->setTemplateRepository($_SERVER['DOCUMENT_ROOT'].'/benchmark/');
	}
	function emptyTemplate() {
		$this->mock->setForceReparse(true);
		$this->mock->setTemplate("empty.xhtml");
		$this->mock->execute();
	}
	function emptyTemplateCached() {
		$this->mock->setForceReparse(false);
		$this->mock->setTemplate("empty.xhtml");
		$this->mock->execute();
	}
	function listTemplate() {
		$this->mock->list = $this->array;
		$this->mock->setTemplate("list.xhtml");
		return $this->mock->execute();
	}
	
	function tableTemplate() {
		$this->mock->table = $this->table;
		$this->mock->setTemplate("table.xhtml");
		return $this->mock->execute();
	}
}
class SmartyProvider extends TestProvider{
	/**
	 * @var Smarty
	 */
	private $mock ;
	function classLoad() {
		require_once 'Smarty.class.php';
	}
	function objectCreation() {
		$this->mock = new Smarty();
		$this->mock->template_dir = $_SERVER['DOCUMENT_ROOT'].'/benchmark';
		$this->mock->compile_dir  = '/tmp/';
	}
	function emptyTemplate() {
		$this->mock->force_compile = true;
		$this->mock->fetch("empty.tpl");
	}
	function emptyTemplateCached() {
		$this->mock->force_compile = false;
		$this->mock->fetch("empty.tpl");
	}
	function listTemplate() {
		$this->mock->force_compile = false;
		$this->mock->assign('list', $this->array);
		return  $this->mock->fetch("list.tpl");
	}
	function tableTemplate() {
		$this->mock->force_compile = false;
		$this->mock->assign('table', $this->table);
		return  $this->mock->fetch("table.tpl");
	}
}
class Benchmark{
	private $subjects;
	function __construct() {
		 $this->subjects = array('Smarty'=>new SmartyProvider(), 'MicroTal'=>new MicroTalProvider(), 'PhpTal'=> new PhptalProvider());
	}
	function runTest($function, $count = 1) {
		$t = new Timer();
		$result = array();
		foreach($this->subjects as $providerName =>$provider){
			$t->start();
			for($i=0;$i<$count;$i++) {
				$provider->$function();
			}
			$result[$providerName] = $t->stop();
		}
		return $result;
	}
	function runTests($tests){
		echo '<table style="clear:both">';
		echo '<tr><th>Test Name</th><th>Repeats</th>';
		foreach($this->subjects as $providerName =>$provider){
			echo '<th>'.$providerName.'</th>';
		}
		foreach($this->subjects as $providerName =>$provider){
			echo '<th>'.$providerName.' %</th>';
		}
		echo '</tr>';
		foreach($tests as $test){
			echo '<tr><td colspan="'.(2+2*count($this->subjects)).'">';
			$results = $this->runTest($test[1], $test[2]);
			echo '</td></tr>';
			echo '<tr><td>'.$test[0].'</td><td>'.$test[2]."</td>\n";
			$min=PHP_INT_MAX;
			foreach($results as $providerName =>$result){
				echo '<td>'.sprintf("%5.5f", $result)."</td>\n";
				if ($min > $result )$min = $result;
			}
			foreach($results as $providerName =>$result){
				echo '<td>'.sprintf("%5.2f", $result/$min)."</td>\n";
			}
			echo "</tr>\n";
		}
		echo '</table>';
	}
}
//error_reporting(E_STRICT);
//ini_set('display_errors', 1);
//require_once 'smarty/libs/Smarty.class.php';
/*
$a = new SmartyProvider();
$a->classLoad();*/
$benchmark = new Benchmark();

$benchmark->runTests(array(
	array("Class loading","classLoad",1),
	array("Object Creation","objectCreation",1),
	array("Object Creation","objectCreation",1000),
	/*array("Empty Template - nocache ","emptyTemplate",1000),*/
	array("Empty Template","emptyTemplateCached",100),
	array("List Template","listTemplate",100),
	array("List Template (output test)","listTemplateOutput",1),
	array("Table Template","tableTemplate",100),
	array("List Template (output test)","tableTemplateOutput",1),
));